home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_c
/
mscheap2
/
packdemo.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-13
|
5KB
|
190 lines
//
// Copyright (c) 1990 by Optimal Software, All Rights Reserved
//
//
// A demonstration of the heap packing functions _relocate() and _heappack()
//
// 1. Allocate random chunks until out of memory.
// 2. Free a percentage of the chunks (optional command line parameter)
// 3. Relocate the remaining chunks until nothing moves
// 4. Release memory to DOS
//
// Usage: PACKDEMO [percent_to_free]
//
// The default for the percent_to_free is 50.
//
// An interesting variation is to reverse the order of the relocation
// scan to see what effect it has on the number of passes needed to
// fully compress the heap. It appears that a high-to-low pass usually
// requires multiple passes, while a low-to-high pass has only a small
// chance of needing more than 1 pass to fully compress the heap. Also
// the upward scan seems to produce signifigantly higher packing factors
// than the downward scan. These effects are independent of the heap
// usage factor (percent of free heap memory -- command line parameter).
//
#define FALSE 0
#define TRUE (!FALSE)
#define VERBOSE FALSE /* set TRUE to get detailed before/after heap dumps */
#include <stdio.h>
#include <stdlib.h>
#include <heap.h>
int main( int argc, char *argv[] )
{
typedef struct tag
{
struct tag far *next;
struct tag far *last;
} NODE;
NODE prealloc, far *head = &prealloc, far *tmp, far *scan;
int dispose = 50, count = 0, status;
if (argc > 1)
dispose = atoi( argv[1] ); /* percent to deallocate */
srand(12345);
//
// Init linked list
//
head->next = head;
head->last = head;
//
// Add entries to the list until malloc() fails
//
// This code builds the list in order of increasing address
//
while ( ( tmp = _fmalloc( sizeof(NODE) + (rand() % 1000) ) ) != NULL )
{
tmp->next = head;
tmp->last = head->last;
tmp->next->last = tmp;
tmp->last->next = tmp;
count++;
}
//
// Check for errors
//
if ( (status = _fheapchk() ) != _HEAPOK)
{
printf("Heap error: %s (after allocation sequence)\n", _heapstat( status ) );
_fheapdump( stdout, TRUE );
}
else
{
//
// Deallocate a fraction of the allocated entries
//
count = (int) ( (long) count * dispose / 100 );
scan = head;
while ( count-- > 0 )
{
tmp = scan->next;
if (tmp != head) /* can't free preallocated node */
{
tmp->next->last = tmp->last;
tmp->last->next = tmp->next;
_ffree( tmp );
}
do
{
scan = scan->next; /* add some noise to the deallocation sequence */
}
while (rand() & 1);
}
//
// Check for errors
//
if ( (status = _fheapchk() ) != _HEAPOK)
{
printf("Heap error: %s (after deallocation sequence)\n", _heapstat( status ) );
_fheapdump( stdout, TRUE );
}
else
{
//
// Dump the heap prior to packing
//
printf("\n*** Before packing\n\n");
_fheapdump( stdout, VERBOSE );
//
// Relocate heap entries until nothing moves
//
printf("\n*** Relocation passes...\n\n");
do
{
count = 0;
scan = head->next;
//
// Make a pass through the list attempting to relocate entries
//
while (scan != head)
{
tmp = _frelocate( scan );
if (tmp != NULL) /* did it move? */
{
scan = tmp;
scan->next->last = scan; /* send change-of-address to neighbors */
scan->last->next = scan;
count++;
}
scan = scan->next;
}
//
// Print results of this pass
//
printf("%5u entries relocated; %s\n", count, _heapstat( _fheapchk() ) );
}
while (count > 0);
//
// Release memory to DOS
//
if ( (status = _fheappack() ) != 0)
printf("DOS error %d while packing heap\n", status );
else
{
printf("\n*** After packing\n\n");
_fheapdump( stdout, VERBOSE );
printf("Heap status: %s (after packing)\n", _heapstat( _fheapchk() ) );
}
}
}
return( 0 );
}